package com.study.springsecurity.security.config;

import com.study.springsecurity.constant.CommonConstant;
import com.study.springsecurity.constant.CommonConstant.Role;
import com.study.springsecurity.service.security.DBUserDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.config.core.GrantedAuthorityDefaults;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;

import javax.sql.DataSource;

/**
 * Security配置Bean
 *
 * @Author YL
 * @Create 2024/3/30 10:48
 * @Version 1.0
 */
@Configuration
public class SecurityBeanConfig {


    /**
     * 分层角色配置，通过角色分层，快速实现角色权限继承，使Admin用户可以访问任意接口
     * 将“>”符号作为包含，例如A>B则表示A的权限大于B，所有B能访问的资源，A都可以访问，即使A没有在HttpSecurity中明确配置能访问哪些接口
     *
     * 注：这个仅对web鉴权生效（即只通过HttpSecurity配置的权限生效），对于方法鉴权（通过注解）是不生效的
     * @return
     */
    @Bean
    RoleHierarchy roleHierarchy() {
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        String hierarchy = Role.ROLE_PREFIX + Role.ADMIN_ROLE + " > " + Role.ROLE_PREFIX + Role.H2_ROLE + "\n"
                + Role.ROLE_PREFIX + Role.ADMIN_ROLE + " > " + Role.ROLE_PREFIX + Role.PLAT_USER_ROLE + "\n"
                + Role.ROLE_PREFIX + Role.ADMIN_ROLE + " > " + Role.ROLE_PREFIX + Role.PLAT_MANAGE_ROLE;
        roleHierarchy.setHierarchy(hierarchy);
        return roleHierarchy;
    }

    /**
     * 配置角色权限的默认前缀
     *
     * @return
     */
    @Bean
    public GrantedAuthorityDefaults createGrantedAuthorityDefaults() {
        return new GrantedAuthorityDefaults(CommonConstant.Role.ROLE_PREFIX);
    }

    /**
     * 会话注册表
     *
     * @return
     */
    @Bean
    public SessionRegistryImpl createSessionRegistry() {
        return new SessionRegistryImpl();
    }

    /**
     * 配置认证信息token存储位置（内存）
     *
     * @return
     */
    //@Bean
    public InMemoryTokenRepositoryImpl createInMemoryTokenRepositoryImpl() {
        return new InMemoryTokenRepositoryImpl();
    }

    /**
     * 配置认证信息token存储位置（数据库）
     *
     * @return
     */
    @Bean
    public JdbcTokenRepositoryImpl createJdbcTokenRepositoryImpl(DataSource dataSource) {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        jdbcTokenRepository.setCreateTableOnStartup(true); // 初始化创建存储token的表
        return jdbcTokenRepository;
    }

    /**
     * 密码加密方式
     * 在哪里配置到security参考：InitializeUserDetailsManagerConfigurer
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 用户信息查询service
     * 在哪里配置到security参考：InitializeUserDetailsManagerConfigurer
     *
     * @return
     */
    @Bean
    public UserDetailsService userDetailsService() {
        return new DBUserDetailsService();
    }
}
